﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using PalFramework.Object;
using PalBattleEmulator.Object.Unit;
using PalBattleEmulator.Battle;
using PalBattleEmulator.Object.Effect;

namespace PalBattleEmulator.Graphic
{
    /// <summary>
    /// UnitLayerControl.xaml 的交互逻辑
    /// </summary>
    public partial class UnitLayer : UserControl
    {
        private List<UnitGraphic> characters;

        public List<UnitGraphic> Characters
        {
            get { return characters; }
        }

        private List<UnitGraphic> enemys;

        public List<UnitGraphic> Enemys
        {
            get { return enemys; }
        }

        private List<EffectGraphic> effects;

        public List<EffectGraphic> Effects
        {
            get { return effects; }
            set { effects = value; }
        }

        public UnitLayer()
        {
            InitializeComponent();
            this.BeginInit();
            this.Width = GlobalConfig.GRAPHIC_WIDTH;
            this.Height = GlobalConfig.GRAPHIC_HEIGHT;
            this.EndInit();
        }

        public void BattleInitialize(GameBattle battle)
        {
            List<IUnit> characterList = battle.CharacterTeam.Units;
            characters = new List<UnitGraphic>(characterList.Count);
            foreach (IUnit unit in characterList)
            {
                this.Dispatcher.Invoke(new optObjectDelegate(addCharacter), unit);
            }

            List<IUnit> enemyList = battle.EnemyTeam.Units;
            enemys = new List<UnitGraphic>(enemyList.Count);
            foreach (IUnit unit in enemyList)
            {
                this.Dispatcher.Invoke(new optObjectDelegate(addEnemy), unit);
            }

            effects = new List<EffectGraphic>();
            DrawUnits();
        }


        public void DrawUnits()
        {
            this.BeginInit();
            foreach (UnitGraphic control in characters)
            {
                if (control != null)
                    control.Draw();
            }
            foreach (UnitGraphic control in enemys)
            {
                if (control != null)
                    control.Draw();
            }
            this.EndInit();
        }

        private Queue<EffectGraphic> removeQueue = new Queue<EffectGraphic>();

        public void DrawEffects()
        {
            this.BeginInit();
            foreach (EffectGraphic control in effects)
            {
                if (control != null)
                    control.Draw();
                if (control.Finished)
                {
                    removeQueue.Enqueue(control);
                }
            }

            this.EndInit();

            while (removeQueue.Count > 0)
            {
                this.Dispatcher.Invoke(new optObjectDelegate(removeEffect), removeQueue.Dequeue());
            }
        }

        public void PlayEffect(int effectTmplId, int posX, int posY)
        {
            Effect[] effs = EffectFactory.createMagicEffects(effectTmplId, posX, posY);
            foreach (Effect eff in effs)
            {
                this.Dispatcher.Invoke(new optObjectDelegate(addEffect), eff);
            }

            while (effects.Count > 0)
            {
                DrawEffects();
                ContextModules.GameClockManager.Sleep(10);
            }
        }

        #region delegate methods

        private delegate void optObjectDelegate(object unit);

        private void addCharacter(object unit)
        {
            CharacterGraphic control = new CharacterGraphic();
            control.Initialize((ICharacter)unit);
            units.Children.Add(control);
            characters.Add(control);
        }

        private void addEnemy(object unit)
        {
            EnemyGraphic control = new EnemyGraphic();
            control.Initialize((IEnemy)unit);
            units.Children.Insert(0, control);
            enemys.Add(control);
        }

        private void addEffect(object unit)
        {
            EffectGraphic control = new EffectGraphic();
            Effect effect = (Effect)unit;
            control.Initialize(effect);
            units.Children.Add(control);
            effects.Add(control);
        }

        private void removeCharacter(object unit)
        {
            Character character = (Character)unit;
            UnitGraphic control = character.GraphicControl;
            units.Children.Remove(control);
            characters.Remove(control);
        }

        private void removeEnemy(object unit)
        {
            Enemy enemy = (Enemy)unit;
            UnitGraphic control = enemy.GraphicControl;
            units.Children.Remove(control);
            enemys.Remove(control);
        }

        private void removeEffect(object graphic)
        {
            EffectGraphic effectGraphic = (EffectGraphic)graphic;
            effects.Remove(effectGraphic);
            units.Children.Remove(effectGraphic);
        }

        #endregion
    }
}
